// ----------------------------------------------------------------------------
// serialize_pointer_type.cpp
// ----------------------------------------------------------------------------
#include <fw/base/serialize/serialize_pointer_type.h>
#include <fw/base/serialize/serialize_pointer_value.h>
#include <fw/base/serialize/serialize_schema.h>
#include <fw/base/serialize/serialize_status.h>
#include <fw/base/core/assertion.h>
#include <stdio.h>

namespace fw
{
	SerializePointerType::SerializePointerType(const SerializeType* indirectType)
	: m_indirectType(indirectType)
	{
	}
	
	SerializeStatus SerializePointerType::ConvertOne(char*					dstData,
													 const char*			srcData,
													 const SerializeType*	srcType,
													 SerializeAllocator&	allocator,
													 int					arrayCount) const
	{
		FW_ASSERT(srcType);
		const SerializePointerType* srcPointerType = srcType->AsPointerType();
		FW_ASSERT(srcPointerType);
		
		SerializePointerValue pointerValue = srcPointerType->ReadPointerValue(srcData);
		const char* srcP = pointerValue.AsConstCharStar();
		allocator.StorePointerLocation(srcData);
		
		char* dstP = allocator.Alloc(GetIndirectType(),
									 srcPointerType->GetIndirectType(),
									 srcP,
									 arrayCount);
		
		if(dstData)
		{
			SerializePointerValue dstPointerValue = SerializePointerValue::Pointer(dstP);
			WritePointerValue(dstData, dstPointerValue);
		}
		
		return kStatus_Ok;
	}
	
	size_t SerializePointerType::GetSize() const
	{
		return sizeof(void*);
	}
	
	size_t SerializePointerType::GetAlignment() const
	{
		return FW_ALIGNOF(void*);
	}
	
	bool SerializePointerType::IsTerminal(const char*					data,
										  const SerializeScalarValue&	terminatorValue,
										  Hash							terminatorName) const
	{
		FW_UNUSED(terminatorValue);
		SerializePointerValue pointerValue = ReadPointerValue(data);
		const char* p = pointerValue.AsConstCharStar();
		return p == nullptr;
	}
	
	SerializePointerValue SerializePointerType::ReadPointerValue(const char* data) const
	{
		return SerializePointerValue::Pointer(*(const char**)(data));
	}
	
	void SerializePointerType::WritePointerValue(char *data, const fw::SerializePointerValue &value) const
	{
		*(const char**)(data) = value.AsConstCharStar();
	}
	
	SerializeStatus SerializePointerType::FixUp(SerializeSchema &schema)
	{
		return kStatus_Ok;
	}
	
} // namespace fw
